package com.yifeng.repo.base.utils.redis.client;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.net.URI;
import java.net.URISyntaxException;
import java.time.Duration;

/**
 * Created by daibing on 2020/2/7.
 */
public class JedisClient {
    /**
     * redis://[:password]@host:port/db
     */
    private String uri = "redis://:123456@127.0.0.1:6379/0";
    private int maxTotal = 8;
    private int maxIdle = 8;
    private int minIdle = 0;
    private int maxWaitMillis = 1500;
    private boolean blockWhenExhausted = false;
    private boolean testOnBorrow = true;

    /**
     * Redis主从模式使用JedisPool即可（支撑分布式锁），注意：ShardedJedisPool不支持eval和evalsha函数，当前应该不需要。
     */
    private JedisPool jedisPool;

    public void init() throws URISyntaxException {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(maxTotal);
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);

        jedisPoolConfig.setTimeBetweenEvictionRuns(Duration.ofSeconds(30));
        jedisPoolConfig.setMinEvictableIdleTime(Duration.ofSeconds(60));
        // 对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出,不再根据MinEvictableIdleTimeMillis判断 (默认逐出策略)
        jedisPoolConfig.setSoftMinEvictableIdleTime(Duration.ofSeconds(10));

        // 连接耗尽时是否阻塞, false报异常, true阻塞直到超时
        jedisPoolConfig.setBlockWhenExhausted(blockWhenExhausted);
        jedisPoolConfig.setMaxWait(Duration.ofMillis(maxWaitMillis));

        jedisPoolConfig.setTestOnBorrow(testOnBorrow);
        jedisPoolConfig.setTestWhileIdle(true);
        jedisPoolConfig.setTestOnReturn(false);
        jedisPool = new JedisPool(jedisPoolConfig, new URI(uri));
    }

    public void destroy() {
        if (jedisPool == null) {
            return;
        }
        jedisPool.close();
    }

    public Jedis get() {
        if (jedisPool.isClosed()) {
            throw new RuntimeException("Jedis pool is closed!");
        }
        return jedisPool.getResource();
    }

    public void close(Jedis res) {
        if (res == null) {
            return;
        }
        res.close();
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public void setMaxWaitMillis(int maxWaitMillis) {
        this.maxWaitMillis = maxWaitMillis;
    }

    public void setBlockWhenExhausted(boolean blockWhenExhausted) {
        this.blockWhenExhausted = blockWhenExhausted;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }
}
